<?php
// 确保在文件最开头关闭错误显示
ini_set('display_errors', 0); // 关闭页面错误输出
error_reporting(E_ALL); // 错误仍记录到日志
session_start();
require 'db_connect.php';

// 设置响应头为 JSON
header('Content-Type: application/json');

// 身份验证
if (!isset($_SESSION['isLoggedIn']) || !$_SESSION['isLoggedIn'] || $_SESSION['role'] !== 'student') {
    http_response_code(401);
    die(json_encode(['success' => false, 'error' => '未授权访问']));
}

// 获取请求数据
$input = json_decode(file_get_contents('php://input'), true);
if (json_last_error() !== JSON_ERROR_NONE) {
    http_response_code(400);
    die(json_encode(['success' => false, 'error' => '无效的JSON数据']));
}

$offeringID = isset($input['offeringID']) ? intval($input['offeringID']) : 0;
$studentID = $_SESSION['userId'] ?? 0;

if ($offeringID <= 0 || $studentID <= 0) {
    http_response_code(400);
    die(json_encode(['success' => false, 'error' => '参数错误']));
}

// ---------------------- Redis 频率限制 ----------------------
$redis = null;
try {
    $redis = new Redis();
    if (!$redis->connect('127.0.0.1', 6379, 1)) {
        throw new Exception("无法连接Redis");
    }
    // 检查连接有效性
    // if ($redis->ping() !== "+PONG") {
    //     throw new Exception("Redis连接异常,redis->ping是: " . $redis->ping());
    // }

    $rateKey = "student_{$studentID}_enroll_attempts";
    $maxAttempts = 2;
    $timeWindow = 5;

    // 正确传递 Lua 脚本参数（键数量 + 参数）
    $result = $redis->eval(
        "local current = redis.call('GET', KEYS[1])
         if current == false then
             redis.call('SET', KEYS[1], 1, 'EX', ARGV[1])
             return 1
         else
             if tonumber(current) >= tonumber(ARGV[2]) then
                 return -1
             else
                 redis.call('INCR', KEYS[1])
                 return tonumber(current) + 1
             end
         end",
        array($rateKey, $timeWindow, $maxAttempts), //参数顺序：键 + ARGV
        1 // 键的数量（KEYS[1]）
    );

    // ************ 调试日志 ************
    error_log("[防连点调试] 学生 {$studentID} 的计数器值: " . $result);

    if ($result === -1) {
        // ************ 拦截日志 ************
        error_log("[防连点触发] 学生 {$studentID} 请求被拦截");
        http_response_code(429);//客户端错误状态码，请求过于频繁
        die(json_encode(['success' => false, 'error' => "操作过于频繁，请{$timeWindow}秒后再试"]));
    }
    // ************ 日志结束 ************
} catch (Exception $e) {
    // Redis 错误不影响选课流程，但记录日志
    error_log("Redis错误: " . $e->getMessage());
}

// ---------------------- 数据库事务 ----------------------
try {
    $conn->begin_transaction();

    // 检查是否重复选课
    $checkStmt = $conn->prepare("SELECT * FROM Enrollment WHERE StudentID = ? AND OfferingID = ?");
    $checkStmt->bind_param("ii", $studentID, $offeringID);
    $checkStmt->execute();
    if ($checkStmt->get_result()->num_rows > 0) {
        throw new Exception("已选过该课程");
    }

    // 插入选课记录
    $insertStmt = $conn->prepare("INSERT INTO Enrollment (StudentID, OfferingID) VALUES (?, ?)");
    $insertStmt->bind_param("ii", $studentID, $offeringID);
    $insertStmt->execute();

    $conn->commit();
    echo json_encode(['success' => true]);
} catch (Exception $e) {
    $conn->rollback();
    http_response_code(500);
    echo json_encode(['success' => false, 'error' => $e->getMessage()]);
    exit;
}